package cn.yunyichina.provider.pay.service.impl;

import cn.yunyichina.provider.framework.dubbo.service.PacityService;
import cn.yunyichina.provider.framework.dubbo.service.WechatPayService;
import cn.yunyichina.provider.iface.entity.common.ResCommon;
import cn.yunyichina.provider.iface.entity.common.ResponseObject;
import cn.yunyichina.provider.iface.entity.dto.pacity.PacityAccessTokenRequestDTO;
import cn.yunyichina.provider.iface.entity.dto.pacity.PacityAccessTokenResponseDTO;
import cn.yunyichina.provider.pay.constant.AppType;
import cn.yunyichina.provider.pay.constant.MethodRouter;
import cn.yunyichina.provider.pay.constant.ResponseEnum;
import cn.yunyichina.provider.pay.exception.PaySettingNotFoundException;
import cn.yunyichina.provider.pay.service.AccessTokenService;
import cn.yunyichina.provider.pay.service.BaseAccessTokenService;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 获取各开放平台接口调用凭证
 * Created by Lullaby on 2017/2/28.
 */
@Service
public class AccessTokenServiceImpl extends BaseAccessTokenService implements AccessTokenService {

    private static final Logger logger = LoggerFactory.getLogger(AccessTokenServiceImpl.class);

    /**
     * 获取认证票据
     *
     * @param json
     * @return
     */
    public ResponseObject getAccessTokenOrdinary(String json) {
        logger.info("AccessTokenServiceImpl.getAccessTokenOrdinary.json -> {}", json);

        ResponseObject response = new ResponseObject();

        try {
            Map<String, String> params = JSON.parseObject(json, Map.class);

            String appType = params.get("app_type");
            switch (AppType.valueOf(appType)) {
                case WECHAT:
                    response = getWechatOrdinaryAccessToken(params);
                    break;
                case ALIPAY:
                    response = getAlipayOrdinaryAccessToken(params);
                    break;
                case PACITY:
                    response = getPacityOrdinaryAccessToken(params);
                    break;
                default:
                    response.setResultCodeAndMessage(
                            ResponseEnum.UNSUPPORTED_APP_TYPE.getCode(),
                            ResponseEnum.UNSUPPORTED_APP_TYPE.getMessage()
                    );
                    break;
            }
        } catch (PaySettingNotFoundException e) {
            logger.error("AccessTokenServiceImpl.getAccessTokenOrdinary.PaySettingNotFoundException", e);
            response.setResultCodeAndMessage(
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getCode(),
                    ResponseEnum.PAY_SETTING_NOT_FOUND.getMessage()
            );
        } catch (Exception e) {
            logger.error("AccessTokenServiceImpl.getAccessTokenOrdinary.exception", e);
            response.setResultCodeAndMessage(
                    ResponseEnum.ACCESS_TOKEN_EXCEPTION.getCode(),
                    ResponseEnum.ACCESS_TOKEN_EXCEPTION.getMessage()
            );
        }

        return response;
    }

    /**
     * 获取微信认证票据
     *
     * @param params
     * @return
     * @throws PaySettingNotFoundException
     */
    private ResponseObject getWechatOrdinaryAccessToken(Map<String, String> params) throws PaySettingNotFoundException {
        ResponseObject response = new ResponseObject();

        if (checkGetWechatOrdinaryAccessTokenParameters(params)) {
            Map<String, String> accessTokenParamsMap = buildGetWechatOrdinaryAccessTokenParameters(params);

            String accessTokenParamsStr = JsonUtils.toJsonString(accessTokenParamsMap);
            logger.info("AccessTokenServiceImpl.getWechatOrdinaryAccessToken.accessTokenParamsStr -> {}", accessTokenParamsStr);

            response = WechatPayService.callUnderlineFromInternalObject(
                    MethodRouter.WECHAT_ORDINARY_ACCESS_TOKEN, accessTokenParamsStr
            );

            logger.info("AccessTokenServiceImpl.getWechatOrdinaryAccessToken.response -> {}", JsonUtils.toJsonString(response));

            if (response.isSuccess()) {
                Map<String, String> rpcResultMap = JsonUtils.parseObject(response.getResultObject(), Map.class);

                Map<String, String> result = new HashMap<>();
                result.put("access_token", rpcResultMap.get("access_token"));
                result.put("expires_in", rpcResultMap.get("expires_in"));

                response.setResultObject(result);
            } else {
                response.setResultCodeAndMessage(
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getCode(),
                        ResponseEnum.WECHAT_ACCESS_TOKEN_FAILURE.getMessage()
                );
            }
        } else {
            response.setResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );
        }

        return response;
    }

    /**
     * 获取支付宝认证票据
     *
     * @param params
     * @return
     */
    private ResponseObject getAlipayOrdinaryAccessToken(Map<String, String> params) {
        ResponseObject response = new ResponseObject();

        return response;
    }

    /**
     * 获取平安开放平台授权访问令牌
     *
     * @param params
     * @return
     */
    private ResponseObject getPacityOrdinaryAccessToken(Map<String, String> params) {
        ResponseObject response = new ResponseObject();

        if (!checkGetPacityOrdinaryAccessTokenParameters(params))
            return response.buildResultCodeAndMessage(
                    ResponseEnum.Common.INVALID.getCode(),
                    ResponseEnum.Common.INVALID.getMessage()
            );

        PacityAccessTokenRequestDTO requestDTO = buildGetPacityOrdinaryAccessTokenRequestDTO(params);
        logger.info("AccessTokenServiceImpl.getPacityOrdinaryAccessToken.requestDTO -> {}", JSON.toJSONString(requestDTO));

        ResCommon<PacityAccessTokenResponseDTO> accessTokenResponse = PacityService.getPacityClient().getPacityAccessToken(requestDTO);
        logger.info("AccessTokenServiceImpl.getPacityOrdinaryAccessToken.accessTokenResponse -> {}", JSON.toJSONString(accessTokenResponse));

        PacityAccessTokenResponseDTO responseDTO = accessTokenResponse.getResult();

        if (accessTokenResponse.isSuccess()) {
            response.setResultObject(responseDTO);
        } else {
            response.setResultCodeAndMessageAndResult(
                    accessTokenResponse.getResultCode(),
                    accessTokenResponse.getResultMessage(),
                    responseDTO
            );
        }

        return response;
    }

}
